// ------------------------------------------------------------------------------------------------
// File   : DX9PixelShaderManager.cpp
// Date   : 2012-08-01
// Author : Weng xiao yi
// Descr. : Manage pixel shaders
//          Handles creation by building the shader definition based on requested features
//
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// HEADERS
// ------------------------------------------------------------------------------------------------
#include "DX9ShaderUtils.h"
#include "DX9PixelShader.h"
#include "DX9PixelShaderManager.h"
#include "DX9ShaderDatabase.h"
#include "Shaders\DX9FeatureDefinitions.h"


const CHAR DX9PS_SHADER_ENTRY[]  = "PSMain";

// pixel header format Input : ---------------------------------------------------------
// %s - platform specific defines
// %s - features defines
// %s - shader name
// --------------------------------------------------------------------------------------
const CHAR DX9PS_SHADER_FORMAT[] = 
"\n%s\n\n"                                                      \
"%s\n\n"                                                        \
"#include \"DX9FeatureDefinitions.h\"\n"                        \
"#include \"PsCommon.hlsl\"\n"                                  \
"#include \"%s.hlsl\"\n"                                        \
"%s PSMain( VSOUT Input ) %s\n"                                 \
"{\n"                                                           \
"    return ProcessPixel( Input );\n"                           \
"}\n\n"                                                         \
;

const CHAR DX9PS_SHADER_RETURN[]             = "float4";
const CHAR DX9PS_SHADER_OUTPUT_SEMANTIC[]    = ": COLOR";


const char* FDX9PSMaterialsDesc[] =
{
	"PSDefault",
	"PSConstantColor",
	"PSAfterEffect",
	"PsAdvancedWater",
	"PsSpaceBump",
	"PsSoftParticle",
	"PsDynamicWeather"
};

DX9PixelShaderManager::DX9PixelShaderManager()
{ 
}

DX9PixelShaderManager::~DX9PixelShaderManager()
{
	UnloadAll();
}

void DX9PixelShaderManager::Shutdown(void)
{
	UnloadAll();
}

void DX9PixelShaderManager::UnloadAll(void)
{
	UnloadAllShaders();
}

void DX9PixelShaderManager::UnloadAllShaders(void)
{
	MapPixelShader::iterator it = m_mapLoadedShaders.begin();
	while(it != m_mapLoadedShaders.end())
	{
		delete it->second;
		it->second = NULL;
		it++;
	}
	m_mapLoadedShaders.clear();
}

// ------------------------------------------------------------------------------------------------
// Name   : BuildShaderDefinition
// Params : Features that defines the shader
// RetVal : _szShaderDefinition string containing the definition
// Descr. : Build the shaders definition to be compiled
// ------------------------------------------------------------------------------------------------
void DX9PixelShaderManager::BuildShaderDefinition(DX9PSFeature* _poFeatures, char *_szShaderDefinition)
{
	if(_poFeatures->UseAssemble())
		sprintf_s(_szShaderDefinition, 4096, "%s", _poFeatures->GetAssembleShader());
	else
		sprintf_s(_szShaderDefinition, 4096, DX9PS_SHADER_FORMAT, 
			"",
			_poFeatures->BuildFeatureDefinition(m_szFeatures),          // feature defines
			FDX9PSMaterialsDesc[_poFeatures->GetMaterialID()],          // shader material
			DX9PS_SHADER_RETURN,                                        // Return type
			DX9PS_SHADER_OUTPUT_SEMANTIC                                // Output semantic
			);  
}

// ------------------------------------------------------------------------------------------------
// Name   : GetShader
// Params : Feature list to support
// RetVal : The appropriate compiled shader
// Descr. : Try to find an already compiled shader having the required features. 
//          Else request a shader compilation
// ------------------------------------------------------------------------------------------------
DX9PixelShader* DX9PixelShaderManager::GetShader(DX9PSFeature* _poFeatures)
{
	// look for cached vertex shader for current key
	MapPixelShader::iterator it = m_mapLoadedShaders.find( _poFeatures->GetKey() );

	if( it != m_mapLoadedShaders.end( ) )
	{
		// use cached vertex shader
		return it->second;
	}
	else
	{
		if(GenerateShader(_poFeatures))
		{
			it = m_mapLoadedShaders.find(_poFeatures->GetKey());
			DX9Verify( it != m_mapLoadedShaders.end() );
			return it->second;
		}
		else
		{
			// could not generate shader
			OutputDebugStringA( "Unable to create pixel shader");
		}
	}

	return NULL;
}

// ------------------------------------------------------------------------------------------------
// Name   : GenerateShader
// Params : Required shader feature set
// RetVal : Shader successfully created or not
// Descr. : Build shader definition then push a request for a shader.
//          A fake default entry will automatically be created then the shader compilation thread
//          will asynchronously compile the required shader and swap when done.
// ------------------------------------------------------------------------------------------------
BOOL DX9PixelShaderManager::GenerateShader(DX9PSFeature* _poFeatures)
{
	DX9ShaderMacro oMacros;
	ULONG          ulFlags         = 0;
	char           szShaderDefinition[4096];

	// Macro settings
	oMacros.Clear();

	// using the defined features and material type, generate a shader definition
	BuildShaderDefinition(_poFeatures, szShaderDefinition);

	// Request compilation of that shader
	DX9GetShaderDatabase()->RequestPixelShader(_poFeatures->GetKey(), szShaderDefinition, 
		DX9PS_SHADER_ENTRY, ulFlags, oMacros);
	return TRUE;
}

// ------------------------------------------------------------------------------------------------
// Name   : CreateShader
// Params : Shader key, code, constant table and name
// RetVal : A useable pixel shader
// Descr. : Create a useable vertex shader entity
// ------------------------------------------------------------------------------------------------
DX9PixelShader* DX9PixelShaderManager::CreateShader(const ULONG64& _ulKey, const void* _pCode, ID3DXConstantTable* _pConstantTable, CHAR* _szName)
{
	DX9Verify(_pCode != NULL);

	DX9PixelShader* pShader = NULL;

	pShader = new DX9PixelShader();
	if(pShader == NULL)
		return NULL;

	if(_pConstantTable)
	{
		pShader->SetConstantTable(_pConstantTable);
	}

	if(pShader->ReInit( (DWORD *)_pCode, (SHADERVERSION(_ulKey)<20) ) == FALSE)
	{
		delete pShader;
		pShader = NULL;
		return NULL;
	}

#ifdef SHADER_DEBUG
	pShader->SetFilename(_szName);
#endif

	return pShader;
}

// ------------------------------------------------------------------------------------------------
// Name   : AddShader
// Params : The shader and its key 
// RetVal : 
// Descr. : Try to find an already present shader using this key. Replace old one if found,
//          create a new entry in the pixel shader map if not.
// ------------------------------------------------------------------------------------------------
void DX9PixelShaderManager::AddShader(const ULONG64& _ulKey, DX9PixelShader* _pShader)
{
	MapPixelShader::iterator it = m_mapLoadedShaders.find(_ulKey);

	if(it != m_mapLoadedShaders.end())
	{
		delete it->second;
		it->second = _pShader;
	}
	else
	{
		m_mapLoadedShaders[_ulKey] = _pShader;
	}
}

// ------------------------------------------------------------------------------------------------
// Name   : AddCreateShader
// Params : 
// RetVal : 
// Descr. : Create and add a new pixel shader
// ------------------------------------------------------------------------------------------------
void DX9PixelShaderManager::AddCreateShader(const ULONG64& _ulKey, const void* _pCode, ID3DXConstantTable* _pConstantTable)
{
	DX9PixelShader* pPixelShader;
	char             szShaderName[64];

	sprintf_s(szShaderName, "0x%016I64x.hlsl", _ulKey);

	pPixelShader = CreateShader(_ulKey, _pCode, _pConstantTable, szShaderName);

	AddShader(_ulKey, pPixelShader);
}

// ------------------------------------------------------------------------------------------------
// Name   : PreLoadShader
// Params : 
// RetVal : 
// Descr. : Add an entry for a previously compiled shader (shaderdatabase). The constant table 
//          will automatically be generated by the create shader.
// ------------------------------------------------------------------------------------------------
void DX9PixelShaderManager::PreLoadShader(const ULONG64& _ulKey, void* _pCode)
{
	AddCreateShader(_ulKey, _pCode, NULL);
}

// ------------------------------------------------------------------------------------------------
// Name   : BuildFeatureDefinition
// Params : 
// RetVal : 
// Descr. : Feature string builder entry point for all pixel shaders
// ------------------------------------------------------------------------------------------------
const char* DX9PixelShaderManager::DX9PSFeature::BuildFeatureDefinition(char *_szFeatureDefinition)
{
	_szFeatureDefinition[0] = '\0';

	DX9_APPEND_DEFINE(1, "PIXEL_SHADER");

	AddSpecificFeatures(_szFeatureDefinition);

	return _szFeatureDefinition;
}

void DX9PixelShaderManager::DX9PSFeatureConstantColor::AddSpecificFeatures(CHAR *_szFeatureDefinition)
{
	//DX9_APPEND_DEFINE(stKey.ulUseFog,           "OUTPUT_FOG_COLOR");
}

void DX9PixelShaderManager::DX9PSFeatureAfterEffect::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	char szTemp[512];

	// After Effect Id
	sprintf_s(szTemp, "AFTER_EFFECT_ID %d", stKey.ulEffectId);
	DX9_APPEND_DEFINE(1, szTemp);

	// After Effect sub type
	sprintf_s(szTemp, "AFTER_EFFECT_SUB_TYPE %d", stKey.ulEffectSubType);
	DX9_APPEND_DEFINE(1, szTemp);

	// Samples count
	sprintf_s(szTemp, "AFTER_EFFECT_SAMPLE_COUNT %d", stKey.ulSamplesCount);
	DX9_APPEND_DEFINE(1, szTemp);
}

void DX9PixelShaderManager::DX9PSFeatureAfterEffect::PreCache()
{
	DX9PixelShader* pPixelShader = NULL;

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature1;
	oPSFeature1.stKey.ulShaderVer	  = 20;
	oPSFeature1.stKey.ulEffectId      = AE_TYPE_BLOOM_DOWNSAMPLE;
	oPSFeature1.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature1);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature2;
	oPSFeature2.stKey.ulShaderVer	  = 20;
	oPSFeature2.stKey.ulEffectId      = AE_TYPE_BLOOM_BLUR;
	oPSFeature2.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature2);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature3;
	oPSFeature3.stKey.ulShaderVer	  = 20;
	oPSFeature3.stKey.ulEffectId      = AE_TYPE_BLOOM_COMBINE;
	oPSFeature3.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature3);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature4;
	oPSFeature4.stKey.ulShaderVer	  = 20;
	oPSFeature4.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oPSFeature4.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature4);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature4_1;
	oPSFeature4_1.stKey.ulShaderVer		= 20;
	oPSFeature4_1.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oPSFeature4_1.stKey.ulEffectSubType = AE_TYPE_FOG_LINEAR_EXP;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature4_1);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature4_2;
	oPSFeature4_2.stKey.ulShaderVer		= 20;
	oPSFeature4_2.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oPSFeature4_2.stKey.ulEffectSubType = AE_TYPE_FOG_LINEAR_EXP2;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature4_2);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature6;
	oPSFeature6.stKey.ulShaderVer	  = 20;
	oPSFeature6.stKey.ulEffectId      = AE_TYPE_FOG_LAYERED;
	oPSFeature6.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature6);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature7;
	oPSFeature7.stKey.ulShaderVer		= 20;
	oPSFeature7.stKey.ulEffectId		= AE_TYPE_FXAA;
	oPSFeature7.stKey.ulEffectSubType	= 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature7);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature8_1;
	oPSFeature8_1.stKey.ulShaderVer		= 20;
	oPSFeature8_1.stKey.ulEffectId      = AE_TYPE_DOF;
	oPSFeature8_1.stKey.ulEffectSubType = AE_TYPE_DOF_TWO_KERNEL_HEXAGONS;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature8_1);


	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature8_3;
	oPSFeature8_3.stKey.ulShaderVer		= 20;
	oPSFeature8_3.stKey.ulEffectId      = AE_TYPE_DOF;
	oPSFeature8_3.stKey.ulEffectSubType = AE_TYPE_DOF_COMBINE;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature8_3);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature9;
	oPSFeature9.stKey.ulShaderVer	  = 20;
	oPSFeature9.stKey.ulEffectId      = AE_TYPE_HeadLight;
	oPSFeature9.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature9);

	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature10;
	oPSFeature10.stKey.ulShaderVer	   = 20;
	oPSFeature10.stKey.ulEffectId      = AE_TYPE_Gamma;
	oPSFeature10.stKey.ulEffectSubType = 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature10);

}


void DX9PixelShaderManager::DX9PSFeatureAdvancedWater::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	char szTemp[512];

	// Volume fog Id
	sprintf_s(szTemp, "ADVANCEDWATER_ID %d", stKey.ulWaterPassID);
	DX9_APPEND_DEFINE(1, szTemp);
}

const CHAR* DX9PixelShaderManager::DX9PSFeatureAdvancedWater::GetAssembleShader()
{
	if(stKey.ulWaterPassID == ADVANCEDWATER_TYPE_REFRACTIONMASK)
	{
		const CHAR* AsmPixelString = 
			"ps_1_1\n"					\
			"def c0, 0,0,0,0\n"			\
			"mov r0, c0\n"				\
			"";
		return AsmPixelString;
	}

	return NULL;
}

void DX9PixelShaderManager::DX9PSFeatureAdvancedWater::PreCache()
{
	DX9PixelShader* pPixelShader = NULL;

	DX9PixelShaderManager::DX9PSFeatureAdvancedWater oPSFeature;
	oPSFeature.stKey.ulShaderVer		= 11;
	oPSFeature.stKey.ulWaterPassID		= ADVANCEDWATER_TYPE_REFRACTIONMASK;
	oPSFeature.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature);

	DX9PixelShaderManager::DX9PSFeatureAdvancedWater oPSFeature2;
	oPSFeature2.stKey.ulShaderVer		= 20;
	oPSFeature2.stKey.ulWaterPassID		= ADVANCEDWATER_TYPE_SURFACERENDER;
	oPSFeature2.stKey.ulAssemble		= 0;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature2);

}

//////////////////////////////////////////////////////////////////////////
const CHAR* DX9PixelShaderManager::DX9PSFeatureShadowmap::GetAssembleShader()
{
	if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_CASTSHADOWMAP )
	{
		const CHAR* AsmPixelString = 
			"ps_1_4															\n"\
			"//																\n"\
			"// 2Kx1 depth pack texture for z value			s1  			\n"\
			"// Diffuse Texture								s0				\n"\

			"def c0, 0,0,0,0												\n"\
			"texld r0, t0													\n"\
			"// Look up into 2Kx1 texture using z value from vertex shader	\n"\
			"texld r1, t1													\n"\
			"mov r2, r0.a													\n"\
			"// Output Texture alpha in alpha channel						\n"\
			"mov r0, r1														\n"\
			"mov r0.a, r2.a													\n"\
			"";
		return AsmPixelString;

	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_RECEIVESHADOW )
	{
		const CHAR* AsmPixelString = 
			"// With 4 higher tan 8-bit precision samples and percentage closer filtering	\n"\
			"//												\n"\
			"// 	s0  		shadowmap					\n"\
			"//		s1			shadowmap					\n"\
			"// 	s2  		shadowmap					\n"\
			"//		s3			shadowmap					\n"\
			"//		s4			diffusemap					\n"\
			"//		s5			CloudLayerTexMap			\n"\
			"//		c0			shadow Intensity			\n"\
			"//		v1			depth and DOF value			\n"\
			
			"ps_1_4											\n"\

			"// Sample weights (1/4)						\n"\
			"def c3, 0.25, 0.25, 0.25, 0.25					\n"\

			"// Fatch 4 shadow map samples					\n"\
			"texld r0, t0									\n"\
			"texld r1, t1									\n"\
			"texld r2, t2									\n"\
			"texld r3, t3									\n"\


			"// Unpack sample								\n"\
			"mov_d8 r0.r, r0.r								\n"\
			"add r0.r, r0.r, r0.g							\n"\

			"mov_d8 r1.r, r1.r								\n"\
			"add r0.g, r1.r, r1.g							\n"\

			"mov_d8 r2.r, r2.r								\n"\
			"add r0.b, r2.r, r2.g							\n"\

			"mov_d8 r3.r, r3.r								\n"\
			"add r1.r, r3.r, r3.g							\n"\

			"phase											\n"\
			"texld r4, t4									\n"\
			"// Sample Cloud Layer texture when no shadow	\n"\
			"texld r5, t5									\n"\
	
			"// cloud shadow not too dark clamp(1-r5.a, c0, 1.0)	\n"\
			"sub_sat r5, 1-r5.a, c0							\n"\
			"add r5, r5, c0									\n"\

			"// Restore sample 3							\n"\
			"mov r0.a, r1.r									\n"\
			"// Light space depth from vertex shader v1		\n"\
			"// Compare shadow map samplers to surface depth\n"\
			"sub r2, r0, v1.y 								\n"\
			"cmp r2, r2, r5, c0								\n"\

			"// r0.r is DOF blend factor from v1.x			\n"\
			"// r0.b is depth from v1.z						\n"\
			"mov r0, v1										\n"\

			"// Average	shadow factor						\n"\
			"// r0.g is shadow factor						\n"\
			"dp4 r0.g, r2, c3								\n"\

			"mov r0.a, r4.a									\n"\
			"";
		return AsmPixelString;
	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_STUDIOTERRAIN_RENDER )
	{
		const CHAR* AsmPixelString = 
			"// 	s0  		diffusemap					\n"\
			"//		s4			Depthshadowmap				\n"\
			"//		c2			Texture coord offset		\n"\

			"ps_1_4											\n"\
			"def c0, 0.5, -0.5, 0.5, 0.5					\n"\
			"def c1, 0.5, 0.5, 0, 0							\n"\
			"// Ambient color								\n"\
			"def c4, 0.2, 0.2, 0.2, 0.2						\n"\
			
			"texcrd  r5.rg,  t4_dw.xyw						\n"\

			"mov r5.w, c1.w									\n"\
			"mov r5.z, c1.z									\n"\
			"mad r5, r5, c0, c1								\n"\
			"add r5, r5, c2									\n"\
			
			"phase											\n"\
			"texld r0, t0									\n"\
			"texld r4, r5.xyz								\n"\
			"// r4.g is shadow factor						\n"\
			"mov r3.xyzw, r4.g								\n"\
			"mul_x2 r1, r0, v0								\n"\
			"// Modulate with diffuse and add ambient		\n"\
			"mad r0, r1, r3, c4								\n"\

			"";
		return AsmPixelString;
	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_OBJWITHSHADOW_RENDER )
	{
		const CHAR* AsmPixelString = 
			"//		s0			Diffusemap					\n"\
			"//		s1			Lightmap					\n"\
			"//		s2			Depthshadowmap				\n"\
			"//		c2			Texture coord offset		\n"\
			"//		c2.z		use lightmap ? 1 : -1		\n"\



			"ps_1_4											\n"\
			"def c0, 0.5, -0.5, 0.5, 0.5					\n"\
			"def c1, 0.5, 0.5, 0, 0							\n"\


			"texcrd  r5.rg, t2_dw.xyw						\n"\
			"mov r5.w, c1.w									\n"\
			"mov r5.z, c1.z									\n"\
			"mad r5, r5, c0, c1								\n"\
			"add r5, r5, c2									\n"\

			"phase											\n"\
			"// r0 is Diffuse color							\n"\
			"texld r0, t0									\n"\
			"// r1 is Lightmap color						\n"\
			"texld r1, t1									\n"\
			"// r2 is shadowmap								\n"\
			"texld r2, r5.xyz								\n"\

			"// r2.g is shadow factor						\n"\
			"mul r0.rgb, r0, r2.g							\n"\
			"// Vertex color modulate2x						\n"\
			"mov_x2 r4, v0									\n"\

			"cmp r5, c2.zzzz, r1, r4						\n"\

			"// diffuse * lightmap * shadow					\n"\
			"// or diffuse*vertex*shadow*2					\n"\
			"mul r0, r0, r5									\n"\

			"";
		return AsmPixelString;
	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_WORLDTERRAIN_RENDER )
	{
		const CHAR* AsmPixelString = 
			"//		s4			Depthshadowmap				\n"\
			"//		c2			Texture coord offset		\n"\

			"ps_1_4											\n"\
			"def c0, 0.5, -0.5, 0.5, 0.5					\n"\
			"def c1, 0.5, 0.5, 0, 0							\n"\

			"texcrd  r5.rg,  t4_dw.xyw						\n"\

			"mov r5.w, c1.w									\n"\
			"mov r5.z, c1.z									\n"\
			"mad r5, r5, c0, c1								\n"\
			"add r5, r5, c2									\n"\

			"phase											\n"\
			"texld r4, r5.xyz								\n"\

			"// r4.g is shadow factor						\n"\
			"mov r3.xyzw, r4.g								\n"\

			"// Modulate with diffuse color and add ambient	\n"\
			"mul r0, v0, r3									\n"\

			"";
		return AsmPixelString;
	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_RECEIVESHADOW_UI )
	{
		const CHAR* AsmPixelString = 
			"//		s0			Depthshadowmap				\n"\

			"ps_1_4											\n"\
			"def c0, 1, 1, 1, 1								\n"\
			"// Ambient color								\n"\
			"def c4, 0.2, 0.2, 0.2, 0.2						\n"\

			"texld r0, t0									\n"\

			"// r0.g is shadow factor						\n"\
			"mov r3.xyzw, r0.g								\n"\

			"// add ambient(shadow color)					\n"\
			"add r0, r3, c4									\n"\
			"mov r0.a, c0.a									\n"\

			"";
		return AsmPixelString;
	}
	else if( stKey.ulshadowPassID == GPUSHADOWMAP_TYPE_ALPHADOFDEPTH )
	{
		const CHAR* AsmPixelString = 
			"ps_1_4											\n"\
			"def c0, 1, 1, 1, 1								\n"\

			"texld r0, t0									\n"\
			"// vertex alpha								\n"\
			"texcrd r4.xyz, t4								\n"\
			"// Light space depth from vertex shader		\n"\
			"texcrd r5.xyz, t5								\n"\

			"// Also setting r0.g but Output color channel is only R B A		\n"\
			"// r0.r is DOF blend factor					\n"\
			"mov r0.r, r5.z									\n"\
			"mov r0.g, c0.g									\n"\

			"// r0.b is depth from r5.y						\n"\
			"mov r0.b, r5.y									\n"\
			"// Also need output alpha						\n"\
			"mul r0.a, r4.r, r0.a							\n"\

			"";
		return AsmPixelString;
	}
	return NULL;
}

void DX9PixelShaderManager::DX9PSFeatureShadowmap::PreCache()
{
	DX9PixelShader* pPixelShader = NULL;

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature1;
	oPSFeature1.stKey.ulShaderVer			= 14;
	oPSFeature1.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_CASTSHADOWMAP;
	oPSFeature1.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature1);

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature2;
	oPSFeature2.stKey.ulShaderVer			= 14;
	oPSFeature2.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_RECEIVESHADOW;
	oPSFeature2.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature2);

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature3;
	oPSFeature3.stKey.ulShaderVer			= 14;
	oPSFeature3.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_STUDIOTERRAIN_RENDER;
	oPSFeature3.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature3);

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature4;
	oPSFeature4.stKey.ulShaderVer			= 14;
	oPSFeature4.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_WORLDTERRAIN_RENDER;
	oPSFeature4.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature4);


	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature6;
	oPSFeature6.stKey.ulShaderVer			= 14;
	oPSFeature6.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_RECEIVESHADOW_UI;
	oPSFeature6.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature6);

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature7;
	oPSFeature7.stKey.ulShaderVer			= 14;
	oPSFeature7.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_ALPHADOFDEPTH;
	oPSFeature7.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature7);

	DX9PixelShaderManager::DX9PSFeatureShadowmap oPSFeature8;
	oPSFeature8.stKey.ulShaderVer			= 14;
	oPSFeature8.stKey.ulshadowPassID		= GPUSHADOWMAP_TYPE_OBJWITHSHADOW_RENDER;
	oPSFeature8.stKey.ulAssemble			= 1;
	pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature8);

}

void DX9PixelShaderManager::DX9PSFeatureSpaceBump::PreCache()
{
	DX9PixelShaderManager::DX9PSFeatureSpaceBump oPSFeature;
	oPSFeature.stKey.ulShaderVer = 20;
	DX9PixelShader* pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature);

}




void DX9PixelShaderManager::DX9PSFeatureSoftParticle::PreCache()
{
	DX9PixelShaderManager::DX9PSFeatureSoftParticle oPSFeature;
	oPSFeature.stKey.ulShaderVer = 20;
	DX9PixelShader* pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature);
}

void DX9PixelShaderManager::DX9PSFeatureDynamicWeather::PreCache()
{
	DX9PixelShaderManager::DX9PSFeatureDynamicWeather oPSFeature;
	oPSFeature.stKey.ulShaderVer = 20;
	DX9PixelShader* pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature);
}
